package edu.hawaii.duedates;

//import java.io.File;
//import java.io.FileNotFoundException;
//import java.io.FileOutputStream;
//import java.io.IOException;
//import java.io.PrintStream;
import java.util.ArrayList;
import java.util.List;

/**
 * ErrorLogger logs the error stack and determines whether which output is
 * most appropriate for a developer or ordinary user.
 * 
 * @author Anthony M. Du
 */

public class ErrorLogger {

  // List for command line arguments.
  private final List<String> args = new ArrayList<String>();
  // List for command line options.
  private final List<String> options = new ArrayList<String>();
  // List for command line parameters (arguments w/o options).
  private final List<String> params = new ArrayList<String>();
  // Log options.
  private static final String[] LOG_OPTIONS = {"-verbose", "-v"};

  /**
   * ErrorLogger default constructor.
   */
  public ErrorLogger() {
    // Do nothing.
  }

  /**
   * ErrorLogger constructor which sets "args" given the argument.
   * 
   * @param args The command line arguments
   */
  public ErrorLogger(String[] args) {
    initialize(args);
  }

  /**
   * Initialize arguments and options.
   * @param args String[] parameter passed from constructor.
   */
  private void initialize(String[] args) {
    // Iterate through each args element.
    for (String s : args) {
      // Store argument to args list.
      this.args.add(s);
      // Check 's' is option?
      if (isOption(s)) {
        // Store 's' as a found option.
        this.options.add(s);
      }
      else {
        // Store 's' as a non option parameter.
        this.params.add(s);
      }
    }
  }

  /**
   * Returns a boolean signifying the on/off of verbose option.
   * @return Boolean of true/false.
   * @throws NullPointerException in isVerbose.
   */
  public boolean isVerbose() throws NullPointerException {
    String[] opts = getOptions();
    // Check if options array has any elements or is null
    if (opts == null) {
      return false;
    }
    // Iterate through each option argument.
    for (String op : opts) {
      try {
        if (op.equals(LOG_OPTIONS[0]) || op.equals(LOG_OPTIONS[1])) {
          return true;
        }
      }
      catch (NullPointerException n) {
        return false;
      }

    }
    return false;
  }

  /**
   * Determines if a passed string is a valid option.
   * 
   * @param str String to test option validity.
   * @return The boolean value of true for option and false for not option. 
   */
  private boolean isOption(String str) {
    // Checks to see if contents of "str" is preceded by a hyphen '-'.
    if (str.charAt(0) == '-') {
      // Iterates through each option in "LOG_OPTIONS" array.
      for (String op : LOG_OPTIONS) {
        // Checks if "str" is a valid option.
        if (str.equals(op)) {
          return true;
        }
      }
    }
    // All else return nil object
    return false;
  }

  /**
   * Returns the options determined from the argument list.
   * @return String[] array of options.
   */
  public String[] getOptions() {
    // Convert collection (List) to an array.
    String[] optsArray = options.toArray(new String [options.size()]);
    if (optsArray.length == 0) {
      return null;
    }
    return optsArray;
  }

  /**
   * Returns the arguments passed into "args".
   * @return String[] array of arguments.
   */
  public String[] getArgs() {
    // Convert collection (List) to an array.
    String[] argsArray = args.toArray(new String [args.size()]);
    if (argsArray.length == 0) {
      return null;
    }
    return argsArray;
  }

  /**
   * Returns the parameters of an argument list (params = args - options).
   * @return String[] array of parameters.
   */
  public String[] getParams() {
    // Convert argument list to array.
    String[] paramsArray = params.toArray(new String [params.size()]);
    // Returns null if arguments is empty.
    if (paramsArray.length == 0) {
      return null;
    }
    return paramsArray;
  }

  /**
   * Adds the error to be logged. Errors/Stack dumps are logged into a file under log/.
   * @param er An Exception gets added to logger.
   */
  public void logError(Exception er) {
    // Create file called "log".
//    File logDir;
//    // Create development.log file.
//    File devLog;
//    // File output stream object.
//    FileOutputStream out;
    // Print stream object.
//    PrintStream ps;

    // Check if verbose option is on/off.
    // Errors will only logged if "-verbose" option is passed as argument.
    if (isVerbose()) {
      // Create development log under log/ directory.
//      logDir = new File("log");
//      devLog = new File("log/development.log");
      // Output file stream to file object.
      // This will append to the existing "development.log" file.
//      try {
        // Make directory called "log".
//        if (!logDir.exists()) {
//          logDir.mkdir();
//        }
//        out = new FileOutputStream(devLog, true);
//        ps = new PrintStream(out);
        // Output stack to screen. 
        // System.err.println("**Error has been recorded in log/development.log");
        er.printStackTrace();
        // Write stack dump to file.
//        er.printStackTrace(ps);
//        out.close();
//      }
//      catch (FileNotFoundException fnf) {
//        System.err.println("FileNotFound Exception.");
//      }
//      catch (IOException io) {
//        System.err.println("WARNING There may be a directory that exists " +
//        "or you don't have write access.");
//      }
    }
  }
}
